﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RDotNet;

namespace Zheng
{
    public class RHandler
    {
        string rpath = "C:\\Program Files\\R\\R-4.2.3\\bin\\x64";
        string rhome = "C:\\Program Files\\R\\R-4.2.3";
        string confFile = "C:\\Users\\" + Environment.UserName + "\\.rhandler\\config";
        string[] libraries = { "eplusr", "sp", "raster", "ncdf4", "Matrix", "energy", "FNN", "MBC" };
        REngine engine;
        bool state = false;

        public RHandler()
        {
            if (File.Exists(confFile))
            {
                using (StreamReader sr = new StreamReader(confFile))
                {
                    rpath = sr.ReadLine();
                    rhome = sr.ReadLine();
                }
            }
        }

        public void loadLibraries()
        {
            REngine.SetEnvironmentVariables(rpath, rhome);
            REngine engineOnce = REngine.GetInstance();
            foreach (string lib in libraries)
            {
                try
                {
                    engineOnce.Evaluate("library(" + lib + ")");
                }
                catch
                {
                    engineOnce.Evaluate("options(repos = c(CRAN = \"https://mirrors.sjtug.sjtu.edu.cn/cran\"))");
                    engineOnce.Evaluate("install.packages(\"" + lib + "\")");
                }
            }
            engineOnce.Dispose();
        }
        
        public void EngineStart()
        {
            REngine.SetEnvironmentVariables(rpath, rhome);
            engine = REngine.GetInstance();
            state = true;
        }

        public void qdm(string era5FilePath, string modValFilePath, string modCalFilePath, string modProFilePath)
        {
            foreach (string lib in libraries)
            {
                try
                {
                    engine.Evaluate("library(" + lib + ")");
                }
                catch
                {
                    engine.Evaluate("options(repos = c(CRAN = \"https://mirrors.sjtug.sjtu.edu.cn/cran\"))");
                    engine.Evaluate("install.packages(\"" + lib + "\")");
                }
            }
            CharacterVector era5 = engine.CreateCharacterVector(new[] { era5FilePath });
            engine.SetSymbol("era5", era5);
            CharacterVector molV = engine.CreateCharacterVector(new[] { modValFilePath });
            engine.SetSymbol("molV", molV);
            CharacterVector molC = engine.CreateCharacterVector(new[] { modCalFilePath });
            engine.SetSymbol("molC", molC);
            CharacterVector molP = engine.CreateCharacterVector(new[] { modProFilePath });
            engine.SetSymbol("molP", molP);

            engine.Evaluate("era5_cal <- read.csv(era5,sep='',header=FALSE)");
            engine.Evaluate("mod_cal <- read.csv(molC,sep='',header=FALSE)");
            engine.Evaluate("mod_val <- read.csv(molV,sep='',header=FALSE)");
            engine.Evaluate("mod_proj <- read.csv(molP,sep='',header=FALSE)");

            engine.Evaluate("fit.qdm_val <- QDM(o.c = era5_cal$V1, m.c = mod_cal$V1, m.p = mod_val$V1, ratio = FALSE)");
            engine.Evaluate("qdm.c <- fit.qdm_val$mhat.c");
            engine.Evaluate("qdm.p <- fit.qdm_val$mhat.p");
            engine.Evaluate("write.csv(qdm.c, sub(\".csv\", \"_bc_qdm.csv\", molC))");
            engine.Evaluate("qdm.p <- fit.qdm_val$mhat.p");
            engine.Evaluate("write.csv(qdm.p, sub(\".csv\", \"_bc_qdm.csv\", molV))");
            engine.Evaluate("fit.qdm_proj <- QDM(o.c = era5_cal$V1, m.c = mod_cal$V1, m.p = mod_proj$V1, ratio = FALSE)");
            engine.Evaluate("qdm.pp <- fit.qdm_proj$mhat.p");
            engine.Evaluate("write.csv(qdm.pp, sub(\".csv\", \"_bc_qdm.csv\", molP))");
        }

        public void HelloTest()
        {
            CharacterVector charVec = engine.CreateCharacterVector(new[] { "Hello, R world!, .NET speaking" });
            engine.SetSymbol("greetings", charVec);
            engine.Evaluate("str(greetings)");
        }

        public bool Started()
        {
            return state;
        }
    }


}

